// playground 创建
window.main = async() => {
    await new Promise(scratchInit);
    (new APIS()).render();
}

function scratchInit(resolve) {
    // 实例化
    var mscratch = new Mscratch({'lang': 'zh'});

    //注入
    mscratch.inject('scratch');

    mscratch.onRendered(() => {
        // 开启代码编辑
        mscratch
            .code
            .setCodeEditable(true);
        mscratch
            .code
            .setRunBtnVisible(true);
        // 假设外部已连接，并使用下面方法通告了连接状态
        mscratch
            .connection
            .onConnect((device) => {
                mscratch
                    .connection
                    .setState(device, true);
            });
        // 假设外部已连接，并使用下面方法通告了连接状态
        mscratch
            .connection
            .onDisconnect((device) => {
                mscratch
                    .connection
                    .setState(device, false);
            });

        // 监听上传进度
        mscratch
            .code
            .onProgress((err, data) => {
                console.log(err, data);
            });

        openSocket();

        const workerDescription = {
            id: 'workerExtension',
            name: {
                en: 'Worker Extension',
                zh: 'Worker扩展示例'
            },
            description: {
                en: 'Worker Extension',
                zh: 'Worker扩展示例'
            },
            basic: false,
            data: './static/extensions/demo/demo2.js',
            devices: null,
            autoRegistered: false
        };
        mscratch
            .extensions
            .appendExtensionToLibrary(workerDescription);
        resolve()
    });

    function openSocket() {
        // 由外部确定的传输通道
        var socket = io.connect('http://localhost:8800');

        //设置通道
        socket.on('sensor2web', function (data) {
            // console.log('local received ', data);
            mscratch
                .transporter
                .doReceived(JSON.parse(data));
        });
        let sender = function (buf) {
            if (buf instanceof Uint8Array) { // 兼容神经元
                // console.log('buf', buf);
                buf = Array.from(buf);
            }
            socket.emit('web2sensor', {
                buf: JSON.stringify(buf),
                sensor: 'None'
            });
        }
        mscratch
            .transporter
            .setSender(sender);
    }
}
//api 数据类
class APIS {
    constructor() {
        APIS.ins = this
        // DOM 对象
        this.domtop = document.querySelector('.top')
        this.domlist = document.querySelector('.list')
        this.domapi = document.querySelector('.api')
        this.domlogger = document.querySelector('.logger')
        let mscratch = Mscratch.instance

        // 需要展示的API对象
        this.objects = [
            mscratch,
            mscratch.workspace,
            mscratch.connection,
            mscratch.code,
            mscratch.extensions,
            mscratch.layout,
            mscratch.project
        ].filter(obj => obj && obj.constructor && obj.constructor.signature)
        // mscratch.connection, mscratch.code, mscratch.layout, mscratch.project,
        
        // 找到 API类
        this.classes = this
            .objects
            .map(c => c.constructor)

        // 菜单
        this.list = this
            .classes
            .map(c => c.name)

        // 菜单选项
        this.index = 0
    }

    // 菜单 style
    listItemStyle(picked) {
        let bgColor,
            color
        if (picked) {
            bgColor = 'grey'
            color = 'white'
        } else {
            bgColor = 'white'
            color = 'grey'
        }
        return `"padding:0 1rem;width:100%;background:${bgColor};
    color:${color}"
    `
    }

    // 菜单 click
    onclick(text) {
        this.index = this
            .list
            .indexOf(text)
        return this
    }

    // api 执行
    run(funcName, argNum) {
        let vals = []
        for (let i = 0; i < argNum; ++i) {
            let v = null
            let e = document.getElementById(funcName + i)
            if (e.tagName === 'SELECT') {
                v = '"'+e.options[e.selectedIndex].value+'"'
            } else {
                v = e.value
            }

            try {
                v = eval(v)
            } catch (ex) {
                //string
            }

            vals.push(v)
        }

        let obj = this.objects[this.index]
        let methodOrGetterRes = obj[funcName]
        let r = methodOrGetterRes
        if(typeof(methodOrGetterRes) == 'function'){
            r = methodOrGetterRes.bind(obj)(...vals);
        }
        
        console.log(r);
        this.domlogger.innerText = r? window.inspect(r):'Done';
    }

    //
    renderlistItem(text, picked) {
        return `<div onclick= "APIS.ins.onclick('${text}').render()" style=${this.listItemStyle(picked)}>${text}</div>
    `
    }

    // API 的html生成
    renderapi(funcSig) {
        let inputs = []
        let fname = `<button style='font-size:1rem;' onclick="APIS.ins.run('${funcSig.name}', '${funcSig.arguments.length}')">${funcSig.name}</button>`
        for (let i in funcSig.arguments) {
            let sig = funcSig.arguments[i]
            if (sig.type.option.length !== 0) {
                let options = ''
                for (let op of sig.type.option) {
                    options += `<option id="${funcSig.name + i}" value="${op}">${op}</option>`
                }
                inputs.push(`<select style='font-size:1rem;'id="${funcSig.name + i}">${options}</select>`)
            } else {
                inputs.push(`<input size="4" style='font-size:1rem;' id="${funcSig.name + i}" type="text" name="${sig.name}" placeholder=${sig.name} />`)
            }
        }
        return `<div class='api-item'> ${fname}  ${inputs.join(' ')}</div>`
    }

    // API 的html生成
    renderapis() {
        let r = ''
        let cls = this
            .classes
            .find(cls => cls.name == this.list[this.index])

        for (let m of cls.signature.methods) {
            r += this.renderapi(m)
        }
        return r
    }

    // 菜单渲染
    renderList() {
        let r = ''
        for (let i in this.list) {
            if (i == this.index) {
                r += this.renderlistItem(this.list[i], true)
                continue
            }
            r += this.renderlistItem(this.list[i], false)
        }
        return r
    }

    render() {
        this.domlist.innerHTML = this.renderList()
        this.domapi.innerHTML = this.renderapis()
    }
}

window.APIS = APIS